#include "smart-device-protocol.h"
#include <iostream>
#include <stdio.h>
#include <stdint.h>

SmartDeviceProtocol::SmartDeviceProtocol()
{
}

SmartDeviceProtocol::SmartDeviceProtocol(const vector<uint8_t> &packet)
    : packet(packet)
{
}

void SmartDeviceProtocol::addPacketHead(uint16_t head)
{
    packet.push_back(head >> 8);
    packet.push_back(head & 0xff);
}

void SmartDeviceProtocol::addDeiceAddress(uint32_t addr)
{
    // head = 0xFFFFFFFF
    for (int i = 0; i < 4; i++)
    {
        // 存放最高字节
        // 传送时候高字节在前
        packet.push_back(addr >> 24);
        addr = addr << 8;
    }
}

void SmartDeviceProtocol::addPacketID(uint8_t id)
{
    packet.push_back(id);
}

void SmartDeviceProtocol::addPacketData(uint8_t *data, uint16_t size)
{
    // 添加长度
    packet.push_back(size >> 8);
    packet.push_back(size & 0xff);

    // 添加地址
    for (int i = 0; i < size; i++)
    {
        packet.push_back(data[i]);
    }
}

void SmartDeviceProtocol::addPacketCRC16(void)
{
    uint16_t crc16value = calc_crc16(packet.data(), packet.size());
    packet.push_back(crc16value >> 8);
    packet.push_back(crc16value & 0xff);
}

uint8_t *SmartDeviceProtocol::packetData(void)
{
    return packet.size() ? packet.data() : nullptr;
}

uint16_t SmartDeviceProtocol::packetLen(void)
{
    return packet.size();
}

//================解析应答包的地方Begin================
uint16_t SmartDeviceProtocol::getPacketHead(void) const
{
    packet_t *pkt = (packet_t *)packet.data();
    return (pkt->head[0] << 8 | pkt->head[1]);
}

// 获取地址
uint32_t SmartDeviceProtocol::getPacketAddr(void) const
{
    packet_t *pkt = (packet_t *)packet.data();
    uint32_t packetAddr =
        (pkt->addr[0] << 24) | (pkt->addr[1] << 16) | (pkt->addr[2] << 8) | (pkt->addr[3] << 0);
    return packetAddr;
}

uint8_t SmartDeviceProtocol::getPacketID(void) const
{
    packet_t *pkt = (packet_t *)packet.data();
    return pkt->pid;
}

uint16_t SmartDeviceProtocol::getPacketDataLen(void) const
{
    packet_t *pkt = (packet_t *)packet.data();
    // 错误码+数据
    return (pkt->len[0] << 8 | pkt->len[1]);
}

uint8_t *SmartDeviceProtocol::getPacketData(void) const
{
    packet_t *pkt = (packet_t *)packet.data();
    return getPacketDataLen() ? &pkt->data[0] : nullptr;
}

uint16_t SmartDeviceProtocol::getPacketCRC16(void) const
{
    int packetSize = packet.size();
    return (packet[packetSize - 2] << 8 | packet[packetSize - 1]);
}
uint8_t SmartDeviceProtocol::getPacketErrorCode(void) const
{
    packet_t *pkt = (packet_t *)packet.data();
    return pkt->data[0];
}

void SmartDeviceProtocol::showPacket(void) const
{
    packet_t *pkt = (packet_t *)packet.data();
    // 4个16进制显示 [0] 成员高字节 [1] 低字节
    printf("packet head : %04x\n", getPacketHead());
    printf("packet addr : %08x\n", getPacketAddr());
    printf("packet id   : %02x\n", getPacketID());
    printf("packet len  : %04x\n", getPacketDataLen());
    printf("packet data : ");
    uint16_t datalen = getPacketDataLen();
    uint8_t *data = getPacketData();
    for (int i = 0; i < datalen; i++)
    {
        printf("%02x ", data[i]);
    }
    printf("\n");
    printf("packet sum: %04x\n", getPacketCRC16());
}
bool SmartDeviceProtocol::isErrorPakcet(void)
{
    uint16_t crc16value = calc_crc16(packet.data(), packet.size() - 2);
    return getPacketCRC16() != crc16value;
}
//================解析应答包的地方End================

SmartDeviceProtocol SmartDeviceProtocol::makeDoorLockProtocol(uint8_t deviceType,
                                                              uint8_t opcode,
                                                              uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol;
    protocol.addPacketHead();
    protocol.addDeiceAddress(DOOR_LOCK_DEVICE_ADDR);
    protocol.addPacketID(REQ_PACKET);

    uint8_t data[] = {deviceType, opcode, deviceNumber};
    protocol.addPacketData(data, sizeof(data));
    protocol.addPacketCRC16();

    return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeElectricalProtocol(uint8_t deviceType,
                                                                uint8_t opcode,
                                                                uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol;
    protocol.addPacketHead();
    protocol.addDeiceAddress(ELECTRICAL_DEVICE_ADDR);
    protocol.addPacketID(REQ_PACKET);

    uint8_t data[] = {deviceType, opcode, deviceNumber};
    protocol.addPacketData(data, sizeof(data));
    protocol.addPacketCRC16();

    return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeSensorProtocol(uint8_t deviceType,
                                                            uint8_t opcode,
                                                            uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol;
    protocol.addPacketHead();
    protocol.addDeiceAddress(SENSOR_DEVICE_ADDR);
    protocol.addPacketID(REQ_PACKET);

    uint8_t data[] = {deviceType, opcode, deviceNumber};
    protocol.addPacketData(data, sizeof(data));
    protocol.addPacketCRC16();

    return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeSniffingProtocol(uint8_t deviceType,
                                                              uint8_t opcode,
                                                              uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol;
    protocol.addPacketHead();
    protocol.addDeiceAddress(SNIFFING_DEVICE_ADDR);
    protocol.addPacketID(REQ_PACKET);

    uint8_t data[] = {deviceType, opcode, deviceNumber};
    protocol.addPacketData(data, sizeof(data));
    protocol.addPacketCRC16();

    return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeProtocolFormPacket(const vector<uint8_t> &packet)
{
    return SmartDeviceProtocol(packet);
}
